//
//  XCBluetoothManager.swift
//  XCBlue
//
//  Created by mac on 2025/2/13.
//

import Foundation
import CoreBluetooth

class XCBluetoothManager: NSObject,ObservableObject,CBCentralManagerDelegate, CBPeripheralDelegate {
    
    static let shared = XCBluetoothManager() // 单例实例
    
    @Published var isScanning = false //是否扫描成功
    @Published var discoveredPeripherals:[BlueToothModel] = [] //发现的设备
    @Published var connectedPeripherals:CBPeripheral? //连接的设备
    
    public var centralManager: CBCentralManager! //设备管理
    private let targetServiceUUID = CBUUID(string: "D0FF") //根据这个服务id扫描特征
    private let writeUUID = CBUUID(string: "D004")
    private let readAndNotifyUUID = CBUUID(string: "D002")
    private let filterPeripheraName:[String] = ["BT_ring","Zikr","SC01"] //自家产品前缀
    
    private var writeCharacteristic: CBCharacteristic! //写特征值
    private var readAndNotifyCharacteristic: CBCharacteristic! //读与通知特征值
    private var readAndWriteCharacteristic: CBCharacteristic! //读与写特征值
    
    public var connectBlueModel: BlueToothModel! //连接的设备model
    
    private override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOn:
            //蓝牙开启
            startScanning()
        case .poweredOff:
            print("蓝牙未开启")
        case .resetting:
            print("蓝牙正在重置")
        case .unauthorized:
            print("蓝牙未授权")
        case .unsupported:
            print("设备不支持蓝牙")
        case .unknown:
            print("蓝牙状态未知")
        @unknown default:
            break
        }
    }
    func startScanning() {
        isScanning = true
        centralManager.scanForPeripherals(withServices: nil, options: nil)
        print("开始扫描...")
    }
    
    //发现设备，并过滤
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        if let peripheralName = peripheral.name {
            for prefix in filterPeripheraName {
                if peripheralName.hasPrefix(prefix) {
                    let model = BlueToothModel()
                    model.peripheral = peripheral
                    model.RSSI = RSSI
                    model.advData = advertisementData
                    
                    if let isConnectable = advertisementData["kCBAdvDataIsConnectable"] as? NSNumber {
                        model.isCanConect = isConnectable.boolValue  // 判断是否能连接
                    } else {
                        model.isCanConect = false  // 默认设备不可连接
                    }
                    
                    if let deviceName = advertisementData["kCBAdvDataLocalName"] as? String,!deviceName.isEmpty {
                        model.deviceName = deviceName
                    }else {
                        model.deviceName = peripheralName
                    }
                    if let manufacturerData = advertisementData["kCBAdvDataManufacturerData"] as? Data {
                        let tempAddress = convertToNSString(data: manufacturerData)
                        var tempArr = [String]()
                        
                        if let tempAddress = tempAddress, tempAddress.count == 16 {
                            for i in stride(from: 7, to: 1, by: -1) {
                                let str = tempAddress[tempAddress.index(tempAddress.startIndex, offsetBy: i * 2)..<tempAddress.index(tempAddress.startIndex, offsetBy: (i * 2) + 2)]
                                tempArr.append(String(str))
                            }
                        }
                        
                        let macAddress = tempArr.joined(separator: ":").uppercased()
                        model.macAddress = macAddress
                        
                        if let macAddress = model.macAddress, !discoveredPeripherals.contains(where: { $0.macAddress == macAddress }) {
                            discoveredPeripherals.append(model)
                        }
                        
                    }
                }
            }
        }
    }
    
    //成功连接到设备
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        print("成功连接到设备")
        connectedPeripherals = peripheral
        peripheral.delegate = self
        peripheral.discoverServices(nil)
        
        if let model = discoveredPeripherals.first(where: { $0.peripheral?.identifier == peripheral.identifier }) {
            model.isConnected = true
            connectBlueModel = model
        }
        
    }
    
    //连接设备失败
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        print("连接设备失败")
        if let model = discoveredPeripherals.first(where: { $0.peripheral?.identifier == peripheral.identifier }) {
            model.isConnected = false
            connectBlueModel = nil
        }
        
    }
    //设备断开连接
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        print("设备断开连接")
        connectedPeripherals = nil
        if let model = discoveredPeripherals.first(where: { $0.peripheral?.identifier == peripheral.identifier }) {
            model.isConnected = false
            connectBlueModel = nil
        }
        
        if let error = error as NSError? {
            switch error.code {
            case CBError.connectionTimeout.rawValue:
                print("设备远离了导致的断开")
                NotificationCenter.default.post(name: Notification.Name("kNotiShouldReconnect"), object: nil)
                
            case CBError.peripheralDisconnected.rawValue:
                print("设备主动断开导致的断开")
                NotificationCenter.default.post(name: Notification.Name("kNotiShouldReconnect"), object: nil)
                
            default:
                print("断开失败 error == \(error)")
                return
            }
        }
    }
    
    //发现服务
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        if let error = error {
            print("扫描外设服务出错：\(peripheral.name ?? "未知设备") -> \(error.localizedDescription)")
            return
        }
        
        // 开始扫描特征
        for service in peripheral.services ?? [] {
            print("服务 UUID == \(service.uuid)")
            
            if service.uuid == targetServiceUUID {
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
    }
    
    //发现特征
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        
        if let error = error {
            print("发现特征失败：\(peripheral.name ?? "未知设备") -> \(error.localizedDescription)")
            return
        }
        for characteric in service.characteristics ?? [] {
            
            if characteric.uuid == readAndNotifyUUID {
                if let peripheralModel = connectBlueModel.peripheral,peripheralModel.identifier == peripheral.identifier {
                    print("读与监听特征 UUID == \(characteric.uuid) 权限 == \(characteric.properties)")
                    readAndNotifyCharacteristic = characteric
                    peripheralModel.setNotifyValue(true, for: characteric)
                }else {
                    print("设置读与监听特征时，蓝牙对象不存在或者不一致")
                    //断开连接
                }
                
            }else if characteric.uuid == writeUUID {
                if let peripheralModel = connectBlueModel.peripheral,peripheralModel.identifier == peripheral.identifier {
                    print("写入特征 UUID == \(characteric.uuid) 权限 == \(characteric.properties)")
                    writeCharacteristic = characteric
                    
                    // 发现特征后才算真正连上
                    // 给戒指0.4s的反应时间，再发指令
                    
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) { [weak self] in
                        // 更新连接状态，在这里才算正式连接成功
                        guard let self = self else { return } // 保证 `self` 不为 nil
                        
                        if let model = self.discoveredPeripherals.first(where: { $0.peripheral?.identifier == peripheral.identifier }) {
                            print("设备连接成功")
                            model.isConnected = true
                        }
                    }
                    
                }else {
                    print("获取到写入特征时，蓝牙对象不存在或者不一致")
                    //断开连接
                }
            }
        }
        
    }
    
    //Mark 特征值发生变化时回调
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        print("特征值发生变化时回调== \(String(describing: characteristic.value))")
    }
    
    //发现特征描述的回调
    func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {
        print("发现特征描述的回调")
        print("特征值 = \(String(describing: characteristic.value)) \n")
    }
    
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        print("peripheral = \(peripheral)")
    }
    
    //给硬件发送数据
    func sendMessageToDevice(data:Data) {
        if ((connectBlueModel != nil) && (writeCharacteristic != nil) && data.count > 0) {
            connectBlueModel.peripheral?.writeValue(data, for: writeCharacteristic, type: .withoutResponse)
        }
    }
    
    //发送数据回调
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        print("发送数据回调:\(String(describing: characteristic.value)) error = \(error?.localizedDescription)")
    }
}
